#define  _CRT_SECURE_NO_WARNINGS 1//防止scanf保错
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<windows.h>


typedef struct Student
{
	int ID;//编号
	int Stunum;//学号
	char Name[30];//姓名
	char Sex[10];//性别
	char SetName[20];//系名
	int English;//英语
	int Maths;//数学
	int Cpu;//计算机
}Student;

typedef struct SList//顺序表
{
	Student* data;
	int Size;//数据个数
	int Cap;//空间
}SList;

char HeadLine[100];//存储标题



void SListInit(SList* st)
{	if (!st)//if为真才执行语句
		return;

	
	st->data = NULL;//置空data
	st->Size = 0;
	st->Cap = 0;
}
//插入数据
void SlistInsert(SList* st, Student value)
{
	if (!st)
		return;

	
	if (st->Cap <= st->Size)
	{
		st->Cap = st->Cap == 0 ? 4 : (st->Cap) * 2;
		st->data = (Student*)realloc(st->data, sizeof(Student) * (st->Cap));
		if (!(st->data))
		{
			printf("内存扩展失败！\n");
			exit(EOF);
		}
	}

	(st->data)[st->Size++] = value;//插入完成
}




//读取数据
void ReadData(SList* st)
{
	
	FILE* pf = fopen("./Student.txt", "r");
	if (!pf)
	{
		printf("文件打开失败！\n");
		exit(EOF);
	}
	fgets(HeadLine, 100, pf);

	Student value;
	while (fscanf(pf, "%d%ld%s%s%s%d%d%d", &value.ID, &value.Stunum, value.Name, value.Sex, value.SetName, &value.English, &value.Maths, &value.Cpu) != EOF)//格式化读取，明天说-明天下午考完我有时间就打电话
	{
		SlistInsert(st, value);
	}
	fclose(pf);
}

void WriteData(SList* st)
{
	FILE* pf = fopen("./Student.txt", "w");
	if (!pf)
	{
		printf("文件打开失败！\n");
		exit(EOF);
	}
	fputs(HeadLine, pf);
	for (int i = 0; i < st->Size; ++i)
	{
		fprintf(pf, "%d %ld %s %s %s %d %d %d\n", st->data[i].ID, st->data[i].Stunum, st->data[i].Name, st->data[i].Sex, st->data[i].SetName, st->data[i].English, st->data[i].Maths, st->data[i].Cpu);
	}
	fclose(pf);
}

void SListPrint(SList* st)
{
	if (!st)
		return;

	printf("%s\n", HeadLine);
	for (int i = 0; i < (st->Size); ++i)
	{
		int total = ((st->data)[i].English) + ((st->data)[i].Maths) + ((st->data)[i].Cpu);
		printf("%-6d %-10ld %-8s %-5s %-7s %-5d %-8d %-6d  %-6d\n", (st->data)[i].ID, (st->data)[i].Stunum, (st->data)[i].Name, (st->data)[i].Sex, (st->data)[i].SetName, (st->data)[i].English, (st->data)[i].Maths, (st->data)[i].Cpu, total);
	}
	printf("**************************一共%d条信息*****************************\n\n", (st->Size));
	
}

void FindStudent1(SList* st, int value)
{
	printf("%s\n", HeadLine);
	for (int i = 0; i < (st->Size); ++i)
	{
		if ((st->data)[i].ID == value || (st->data)[i].Stunum == value || (st->data)[i].English == value || (st->data)[i].Maths == value || (st->data)[i].Cpu==value)
		{
			int total = (st->data[i].English) + (st->data[i].Maths) + (st->data[i].Cpu);
			printf("%-6d %-10ld %-8s %-5s %-7s %-5d %-8d %-6d  %-6d\n", st->data[i].ID, st->data[i].Stunum, st->data[i].Name, st->data[i].Sex, st->data[i].SetName, st->data[i].English, st->data[i].Maths, st->data[i].Cpu, total);
		}
	}
}

void FindStudent2(SList* st, char* value)
{
	printf("%s\n", HeadLine);
	for (int i = 0; i < (st->Size); ++i)
	{
		if (strcmp(st->data[i].Name,value) == 0|| strcmp(st->data[i].SetName, value) == 0|| strcmp(st->data[i].Sex,value) == 0)
		{
			int total = (st->data[i].English) + (st->data[i].Maths) + (st->data[i].Cpu);
			printf("%-6d %-10ld %-8s %-5s %-7s %-5d %-8d %-6d  %-6d\n", st->data[i].ID, st->data[i].Stunum, st->data[i].Name, st->data[i].Sex, st->data[i].SetName, st->data[i].English, st->data[i].Maths, st->data[i].Cpu, total);
		}
	}
}

void FindStudent(SList* st)//随机匹配式查找
{
	int order = -1;
	printf("(1)数值查找 (2)文字查找\n请选择> ");
	scanf("%d", &order);
	if(order == 1)
	{
		int value = -1;
		printf("请输入你要查找的数值> ");
		scanf("%d", &value);
		system("cls");
		FindStudent1(st, value);
		system("pause");
	}
	else if (order == 2)
	{
		char value[50];
		printf("请输入你要查找的文字> ");
		scanf("%s", value);
		system("cls");
		FindStudent2(st, value);
		system("pause");
	}
}


int LookUpSub(SList* st, int place)
{
	int i = 0;
	for (i = 0; i < (st->Size); ++i)
	{
		if ((st->data)[i].ID == place)
		{
			break;
		}
	}
	return i;
}

void InsertStudent(SList* st)
{
	//查找指定编号的下标
	printf("请输入插入的位置编号(若编号不存在则默认插入在末尾)> ");
	int place = -1;
	scanf("%d", &place);
	int i = LookUpSub(st, place);
	if (st->Cap <= st->Size)
	{
		st->Cap = st->Cap == 0 ? 4 : (st->Cap) * 2;
		Student* tmp = (Student*)realloc(st->data, sizeof(Student) * (st->Cap));
		if (!(st->data))
		{
			printf("内存扩展失败！\n");
			exit(EOF);
		}
		st->data = tmp;
	}
	Student value;
	printf("请根据提示依次输入以下信息:\n编号 学号     姓名   性别 系名 英语 数学 计算机\n");
	scanf("%d%d%s%s%s%d%d%d", &value.ID, &value.Stunum, value.Name, value.Sex, value.SetName, &value.English, &value.Maths, &value.Cpu);
	for (int k = (st->Size); k > i; --k)
	{
		(st->data)[k] = (st->data)[k - 1];
	}
	(st->data)[i] = value;
	++(st->Size);
}

void EarseStudent(SList* st)
{
	if (st->Size == 0)
		return;

	//查找指定编号的下标
	printf("请输入删除的位置编号> ");
	int place = -1;
	scanf("%d", &place);
	int i = LookUpSub(st, place);

	if (st->data[i].ID != place)
		return;

	for (int k = i; k < (st->Size) - 1; ++k)
	{
		(st->data)[k] = (st->data)[k + 1];
	}
	--(st->Size);
}

void ChangeStudent(SList* st)
{
	char name[50];
	printf("请输入修改学生的姓名> ");
	scanf("%s", name);
	int i = 0;
	for (i = 0; i < (st->Size); ++i)
	{
		if (strcmp((st->data)[i].Name, name) == 0)
		{
			break;
		}
	}
	if (strcmp((st->data)[i].Name, name) != 0)
		return;

	printf("\n1修改编号\n2修改学号\n3修改姓名\n4修改性别\n5修改系名\n6修改英语成绩\n7修改数学成绩\n8修改计算机成绩\n请选择修改项目>");
	int num = -1;
	scanf("%d", &num);
	switch (num)
	{
		case 1:
		{
			printf("请输入新的编号> ");
			scanf("%d", &(st->data)[i].ID);
			break;
		}
		case 2:
		{
			printf("请输入新的学号> ");
			scanf("%d", &(st->data)[i].Stunum);
			break;
		}
		case 3:
		{
			printf("请输入新的姓名> ");
			scanf("%s", (st->data)[i].Name);
			break;
		}
		case 4:
		{
			printf("请输入新的性别> ");
			scanf("%s", (st->data)[i].Sex);
			break;
		}
		case 5:
		{
			printf("请输入新的系名> ");
			scanf("%s", (st->data)[i].SetName);
			break;
		}
		case 6:
		{
			printf("请输入新的英语成绩> ");
			scanf("%d", &(st->data)[i].English);
			break;
		}
		case 7:
		{
			printf("请输入新的数学成绩> ");
			scanf("%d", &(st->data)[i].Maths);
			break;
		}
		case 8:
		{
			printf("请输入新的数学成绩> ");
			scanf("%d", &(st->data)[i].Cpu);
			break;
		}
		default :break;
	}
}

//英语成绩降序排序-冒泡
void EnglishBubbleSort(SList* st)
{
	for (int i = 0; i < st->Size - 1; ++i)
	{
		int flag = 1;
		for (int k = 0; k < st->Size - 1 - i; ++k)
		{
			if (st->data[k].English < st->data[k + 1].English)
			{
				int tmp = st->data[k].English;
				st->data[k].English = st->data[k + 1].English;
				st->data[k + 1].English = tmp;
				flag = 0;
			}
		}
		if (flag)
		{
			break;
		}
	}
}

//数学成绩排序-插入
void MathInsertSort(SList* st)
{
	for (int i = 0; i < st->Size - 1; ++i)
	{
		int end = i;
		int key = st->data[i + 1].Maths;
		while (end >= 0)
		{
			if (st->data[end].Maths < key)
			{
				int tmp = st->data[end].Maths;
				st->data[end].Maths = st->data[end + 1].Maths;
				st->data[end + 1].Maths = tmp;
				--end;
			}
			else
			{
				break;
			}
		}
		st->data[end + 1].Maths = key;
	}
}

void Swap(Student* a, Student* b)
{
	Student tmp = *a;
	*a = *b;
	*b = tmp;
}

//计算机 成绩排序-选择
void CpuSelectSort(SList* st)
{
	int head = 0, end = st->Size - 1;
	while (head < end)
	{
		int maxs = head, mins = head;
		for (int i = head; i <= end; ++i)
		{
			if (st->data[i].Cpu > st->data[maxs].Cpu)
			{
				maxs = i;
			}
			if (st->data[i].Cpu < st->data[mins].Cpu)
			{
				mins = i;
			}
		}
		Swap(&st->data[head], &st->data[maxs]);
		if (mins == head)
		{
			mins = maxs;
		}
		Swap(&st->data[end], &st->data[mins]);
		++head;
		--end;
	}
}

//总分排序
void PointsBubbleSort(SList* st)
{
	for (int i = 0; i < st->Size - 1; ++i)
	{
		int flag = 1;
		for (int k = 0; k < st->Size - 1 - i; ++k)
		{
			int num1 = st->data[k].English + st->data[k].Maths + st->data[k].Cpu;
			int num2 = st->data[k + 1].English + st->data[k + 1].Maths + st->data[k + 1].Cpu;
			if (num1 < num2)
			{
				Student tmp = st->data[k];
				st->data[k] = st->data[k + 1];
				st->data[k + 1] = tmp;
				flag = 0;
			}
		}
		if (flag)
		{
			break;
		}
	}
}

void StudentSort(SList* st)
{
	//英语-冒泡
	//数学-插入
	//计算机-选择
	//总分-冒泡
	printf("1.对英语成绩进行降序排序\n2.对数学成绩进行降序排序\n3.对计算机成绩进行降序排序\n4.对总分进行降序排序\n0.退出排序\n请选择> ");
	int order = -1;
	scanf("%d", &order);
	switch (order)
	{
		case 1:
		{
			EnglishBubbleSort(st);
			break;
		}
		case 2:
		{
			MathInsertSort(st);
			break;
		}
		case 3:
		{
			CpuSelectSort(st);
			break;
		}
		case 4:
		{
			PointsBubbleSort(st);
			break;
		}
		default:break;
	}
}


//销毁顺序表
void SListFree(SList* st)
{
	free(st->data);
	st->data = NULL;
	st->Cap = st->Size = 0;
}

int main()
{
	SList st;
	SListInit(&st);
	ReadData(&st);
	int order = -1;
	do
	{
		system("cls");
		SListPrint(&st);
		printf("1.添加信息\n2.查找信息\n3.删除信息\n4.修改信息\n5.信息排序\n0.退出程序\n请选择> ");
		scanf("%d", &order);
		switch (order)
		{
		case 0: {break; }
		case 1:
		{
			InsertStudent(&st);
			break;
		}
		case 2:
		{
			FindStudent(&st);
			break;
		}
		case 3:
		{
			EarseStudent(&st);
			break;
		}
		case 4:
		{
			ChangeStudent(&st);
			break;
		}
		case 5:
		{
			StudentSort(&st);
			break;
		}
		default: break;
		}
		WriteData(&st);
	} while (order);
	SListFree(&st);
	return 0;
}